package solvoku.model.game;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 * @author Steve Cancès <steve.cances@gmail.com>
 */
public class GroupeCase {

    /**
     * La grille qui contient le groupe de cases
     */
    protected Grille grille;
    /**
     * Les cases du groupe de case
     */
    protected Set<Case> cases;

    public GroupeCase() {
        this(null);
    }

    public GroupeCase(Grille grille) {
        super();
        this.grille = grille;
        this.cases = new HashSet<>();
    }

    /**
     * @return the grille
     */
    public Grille getGrille() {
        return grille;
    }

    /**
     * @param grille the grille to set
     */
    public void setGrille(Grille grille) {
        this.grille = grille;
    }

    /**
     * @return the cases
     */
    public Set<Case> getCases() {
        return cases;
    }

    /**
     * Ajoute la case c au groupe
     *
     * @param c la case a ajouter
     */
    public void addCase(Case c) {
        this.cases.add(c);
    }

    /**
     * Retire la case du groupe
     *
     * @param c la case a retirer
     */
    public void removeCase(Case c) {
        this.cases.remove(c);
    }

    /**
     * Retire toutes les cases du groupe
     */
    public void removeAllCases() {
        this.cases.clear();
    }

    /**
     * Retourn vrai si le groupe contient la case c
     *
     * @param c la case
     * @return vrai i le groupe contient la case c
     */
    public boolean containsCase(Case c) {
        return this.cases.contains(c);
    }

    public boolean majPossibilitesCase(int possibiliteToRemove) {
        boolean ok = true;
        AtomicInteger cpt = new AtomicInteger();
        for (Case c : this.cases) {
            if (c.isVide()) {
                c.removePossibilite(possibiliteToRemove);
                if(c.nbPossibilites() == 0){
                    ok = false;
                }
            } else {
                if(c.getValue() == possibiliteToRemove){
                    cpt.incrementAndGet();
                }
            }
        }
        if(cpt.get() > 1){
            ok = false;
        }
        return ok;
    }

    public CoupAJouer getCoupSimpleAJouer() {
        CoupAJouer coupAJouer = null;
        int cptCasesVides = 0;
        for (Case c : this.cases) {
            if (c.isVide()) {
                cptCasesVides++;
            }
        }
        if (cptCasesVides == 1) {
            Case caseAjouer = null;
            ArrayList<Integer> l = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
            ArrayList<Integer> l2 = new ArrayList<>();
            for (Case c : this.cases) {
                Integer value = c.getValue();
                if (value != 0) {
                    l2.add(value);
                } else {
                    caseAjouer = c;
                }
            }
            l.removeAll(l2);
            coupAJouer = new CoupAJouer(caseAjouer, l.get(0));
        }
        return coupAJouer;
    }

    public CoupAJouer getCoupAJouerPossibiliteUniqueDansGroupe() {
        CoupAJouer coupAJouer = null;
        HashMap<Integer, Integer> hashMapCptPossibilites = new HashMap<>();
        HashMap<Integer, Case> hashMapCptPossibilitesCases = new HashMap<>();
        for (int i = 1; i <= 9; ++i) {
            hashMapCptPossibilites.put(i, 0);
        }
        for (Case c : this.cases) {
            for (Integer possibilite : c.getPossibilites()) {
                hashMapCptPossibilites.put(possibilite, hashMapCptPossibilites.get(possibilite) + 1);
                hashMapCptPossibilitesCases.put(possibilite, c);
            }
        }
        for (Entry<Integer, Integer> entry : hashMapCptPossibilites.entrySet()) {
            if (entry.getValue() == 1) {
                coupAJouer = new CoupAJouer(hashMapCptPossibilitesCases.get(entry.getKey()), entry.getKey());
            }
        }
        return coupAJouer;
    }
}
